package com.yh.csx.bsf.flow.engine;

import com.fasterxml.jackson.core.type.TypeReference;
import com.yh.csx.bsf.core.base.Ref;
import com.yh.csx.bsf.core.util.JsonUtils;
import com.yh.csx.bsf.flow.core.FlowProperties;
import com.yh.csx.bsf.flow.dao.dal.t_task_dal;
import com.yh.csx.bsf.flow.engine.api.Api;
import com.yh.csx.bsf.flow.provider.enums.ModelTypeEnum;
import com.yh.csx.bsf.flow.core.base.ChooseUser;
import com.yh.csx.bsf.flow.core.base.Model;
import com.yh.csx.bsf.flow.core.base.Variable;
import com.yh.csx.bsf.flow.core.base.Xml;
import com.yh.csx.bsf.flow.core.db.DbHelper;
import com.yh.csx.bsf.flow.core.util.ArrayUtil;
import com.yh.csx.bsf.flow.core.util.XmlUtil;
import com.yh.csx.bsf.flow.dao.dal.t_flow_dal;
import com.yh.csx.bsf.flow.dao.dal.t_model_dal;
import com.yh.csx.bsf.flow.dao.model.auto.t_flow_model;
import com.yh.csx.bsf.flow.dao.model.auto.t_model_model;
import com.yh.csx.bsf.flow.engine.state.StateEngine;
import lombok.val;
import lombok.var;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author: chejiangyi
 * @version: 2019-10-29 20:44
 **/
@SpringBootApplication(scanBasePackageClasses = {FlowProperties.class})
public class Test {
    public static void createOrUpdateModel(){
        List<Model.Node> nodes = new ArrayList<>();
        //开始
        var node1 = new Model.Node();
        node1.setTitle("开始");node1.setTypeEnum(Model.TypeEnum.Start);
        node1.setBeginScript("param['a1']='fff';\n" +
                "if('【@a2】'=='aaa'){param['a2']='bbb';}\n" +
                "param['a3']=param['a2'];");
        var route = new Model.Route("自动1","","");
        node1.setRoutes(Arrays.asList(route));
        node1.setEndScript("param['result']=route;");

        //自动1
        var node2 = new Model.Node();
        node2.setTitle("自动1");node2.setTypeEnum(Model.TypeEnum.Auto);
        node2.setBeginScript("param['a1']='mm';\n" +
                "param['a3']='自动1';");
        var route1 = new Model.Route("人工1","","");
        var route2 = new Model.Route("人工2","","");
        node2.setRoutes(Arrays.asList(route1,route2));
        node2.setEndScript("param['result']=route;");

        //人工1
        var node3 = new Model.Node();
        node3.setTitle("人工1");node3.setTypeEnum(Model.TypeEnum.Man);
        node3.setBeginScript("param['a3']='人工1';");
        //*** 审批用户 ***//
        val user = new Model.ApproveUser();
        user.setApproveNum(-1);
        user.setDistributeModeEnum(Model.DistributeModeEnum.Once);
        user.setFilterModeEnum(Model.FilterModeEnum.Order);
        val chooseUsers = new ArrayList<ChooseUser>();chooseUsers.add(new ChooseUser(ChooseUser.UserRoleEnum.Variable,"user","变量", ChooseUser.SetOperationEnum.Union));
        user.setChooseUsers(chooseUsers);
        node3.setApproveUser(user);
        node3.setApproveResults(ArrayUtil.asList(new String[]{"同意","不同意","转交"}));
        var route3 = new Model.Route("自动2","","【num('同意')】==2");
        var route4 = new Model.Route("结束","","【num('不同意')】>0");
        node3.setRoutes(Arrays.asList(route3,route4));
        node3.setEndScript("param['result']=route;param['man1']='true';");
        node3.setStartNotify(Model.NotifyEnum.Mail);
        node3.setEndNotify(Model.NotifyEnum.Mail);

        //人工2
        var node5 = new Model.Node();
        node5.setTitle("人工2");node5.setTypeEnum(Model.TypeEnum.Man);
        node5.setBeginScript("param['a3']='人工2';");
        //*** 审批用户 ***//
        val user5 = new Model.ApproveUser();
        user5.setApproveNum(2);
        user5.setDistributeModeEnum(Model.DistributeModeEnum.OneByOne);
        user5.setFilterModeEnum(Model.FilterModeEnum.Random);
        val chooseUsers5 = new ArrayList<ChooseUser>();chooseUsers5.add(new ChooseUser(ChooseUser.UserRoleEnum.Variable,"user","变量", ChooseUser.SetOperationEnum.Union));
        user5.setChooseUsers(chooseUsers5);
        node5.setApproveUser(user5);
        node5.setApproveResults(ArrayUtil.asList(new String[]{"ok","no","转交"}));
        var route5 = new Model.Route("自动2","","【num('同意')】==2");
        var route6 = new Model.Route("结束","","【num('不同意')】>0");
        node5.setRoutes(Arrays.asList(route5,route6));
        node5.setEndScript("param['result']=route;param['man2']='true';");
        node5.setStartNotify(Model.NotifyEnum.Mail);
        node5.setEndNotify(Model.NotifyEnum.Mail);
        var rules = new Model.TimeOutRule[]{
                new Model.TimeOutRule(1, Model.TimeoutDealWayEnum.Notify,"Mail"),
                new Model.TimeOutRule(2, Model.TimeoutDealWayEnum.Script,"param['a4']='车车';"),
                new Model.TimeOutRule(3, Model.TimeoutDealWayEnum.Transfer,"222"),
        };
        node5.setTimeOutRules(ArrayUtil.asList(rules));

        //自动2
        var node6 = new Model.Node();
        node6.setTitle("自动2");node6.setTypeEnum(Model.TypeEnum.Auto);
        node6.setBeginScript("param['a1']='mm';\n" +
                "param['a3']='自动2';");
        var route7 = new Model.Route("结束","","'【@man1】'=='true'&&'【@man2】'=='true'");
        node6.setRoutes(Arrays.asList(route7));
        node6.setEndScript("param['result']=route;");

        //结束
        var node4 = new Model.Node();
        node4.setTitle("结束");node4.setTypeEnum(Model.TypeEnum.End);

        nodes.add(node1);nodes.add(node2);nodes.add(node3);nodes.add(node4);nodes.add(node5);nodes.add(node6);

        //权限
        List<Model.FormPermission> permissions = new ArrayList<>();
        List<ChooseUser> userhide = new ArrayList<>();
        userhide.add(new ChooseUser(ChooseUser.UserRoleEnum.Variable,"permission_hide","隐藏", ChooseUser.SetOperationEnum.Union));
        List<ChooseUser> userwrite= new ArrayList<>();userwrite.add(new ChooseUser(ChooseUser.UserRoleEnum.Variable,"permission_write","写", ChooseUser.SetOperationEnum.Union));
        var p1 = new Model.FormPermission("人工1","field1", Model.PermissionEnum.write,userwrite);
        var p2 = new Model.FormPermission("人工2","field2", Model.PermissionEnum.hide,userhide);
        permissions.add(p1);
        permissions.add(p2);

        var variable_define = new ArrayList<Variable>();
        variable_define.add(new Variable("a1","aaa","变量1"));variable_define.add(new Variable("a2","","变量2"));
        variable_define.add(new Variable("a3","","变量3"));variable_define.add(new Variable("result","","路由记录"));
        variable_define.add(new Variable("user","80920456,80861579,111,222","用户"));
        variable_define.add(new Variable("permission_hide","80861579","隐藏"));
        variable_define.add(new Variable("permission_write","80920456","写"));
        variable_define.add(new Variable("permission_read","80920456","读"));
        variable_define.add(new Variable("man1","","man1结果"));
        variable_define.add(new Variable("man2","","man2结果"));

        val test = JsonUtils.deserialize(JsonUtils.serialize(nodes), new TypeReference<List<Model.Node>>() {});
        Xml xml = new Xml(variable_define,nodes,permissions);
        val xmlstr = XmlUtil.serialize(xml);
        val obj = XmlUtil.deserialize(xmlstr,Xml.class);
        val model = new t_model_model(0,"flow.test","测试",
                "","",1,(byte) 1,new Date(),new Date(),"车江毅","车江毅", xmlstr,(byte) ModelTypeEnum.common.Value);
        DbHelper.call(c->{
            val dal = new t_model_dal();
            val item = dal.get(c,model.name);
            if(item!=null)
            {
                model.id=item.id;
                dal.edit(c,model);
            }
            else {
                dal.add(c, model);
            }
        });
    }



    public static void createFlow(String modelName){
        Ref<Integer> flowid=new Ref(0);
        DbHelper.transaction(()->{
            var variable_define = new ArrayList<Variable>();
            variable_define.add(new Variable("a1","aaa","变量1"));variable_define.add(new Variable("a2","","变量2"));
            variable_define.add(new Variable("a3","","变量3"));variable_define.add(new Variable("result","","路由记录"));
            variable_define.add(new Variable("a4","","外部变量"));
            variable_define.add(new Variable("money","100","测试"));

            flowid.setData(DbHelper.get(c->{
                val dal2 = new t_model_dal();
                val m = dal2.getUse(c,modelName);
                val variables = XmlUtil.deserialize(m.getXml(), Xml.class).getVariables();
                variables.forEach(v->{
                    var find = variable_define.stream().filter(v2->v2.getKey().equals(v.getKey())).findFirst();
                    if(find.isPresent())
                    {
                        v.setValue(find.get().getValue());
                    }
                });

                val dal = new t_flow_dal();
                val title = modelName+"flow"+new SimpleDateFormat("yy-MM-dd-HH-mm-ss").format(new Date());
                t_flow_model model = new t_flow_model(0,title,"","","",
                        (byte) 1,JsonUtils.serialize(variables),m.id,m.name,m.title,m.version,"80861579",new Date(),"",new Date(),"","");
                return dal.add2(c,model);
            }));
            System.out.println("flowid:"+flowid);
            new StateEngine().flow(flowid.getData());
        });

    }

    public static void doTask(int taskid){
        var variable_define = new ArrayList<Variable>();
        variable_define.add(new Variable("a4","dddd","外部变量"));
        new StateEngine().doTask(taskid,"80861579","同意","测试同意",variable_define);
    }

    public static void transfer(int taskid){
        var variable_define = new ArrayList<Variable>();
        variable_define.add(new Variable("a4","dddd","外部变量"));
        new StateEngine().transfer(taskid,"222","测试转交");
    }

    public static void xmlToJson(){
        t_model_model m = DbHelper.get(c-> {
            val dal2 = new t_model_dal();
            return dal2.getUse(c, "flow.test2");
        });
        Xml xml = XmlUtil.deserialize(m.xml,Xml.class);
        String json = xml.toJson();
        Xml n = new Xml().fromJson(json);
        if(xml.equals(n)==false){
            throw new RuntimeException("错误");
        }
        val a=1;
    }

    public static void main(String[] args) throws Exception{
        Api.httpGet(1,"http://localhost:8082/notify/?tag=1&&message=〖{flowid:1,taskid:2}〗");
//        Api.run(0,"//aaa\n" +
//                "1==0",new HashMap<>());
//        Api.num(0,"【api.num()】==0",new ArrayList<>());
        SpringApplication.run(Test.class, args);
        //xmlToJson();
        //mail();
        //createOrUpdateModel();
        //doTask(7);
        while(true) {
            try {
                //createFlow("预付款申请流程-省区");
                createFlow("test");
            } catch (Exception e) {
                int a = 1;
            }
        }
//        {
//            System.out.println("ok~~~~~~~~~");
//            var max = DbHelper.noTransactionGet((c) -> {
//                return new t_task_dal().max(c);
//            });
//            max = (max == null ? 0 : max);
//            int i = 1;
//            while (true) {
//                try {
//                    doTask(max + i);
//                    i++;
//                } catch (Exception e) {
//                    if (e.getMessage().contains("已处理")) {
//                        i++;
//                        return;
//                    }
//                }
//            }
//        }

        //transfer(105);
        //new TimeoutJob().execute(null);

        //val a =1;

        //transfer();
    }

    public static void mail()
    {
        //Api.mail("80861579","aaaa","aadfadf");
    }

}
